#include "sysmonitor/memory_tools.hpp"
#include "sysmonitor/utils.hpp"
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include <map> 

namespace sysmonitor {
namespace memory {

using namespace utils;
using namespace utils::string;

// 优化: 使用map一次性解析/proc/meminfo，避免重复打开文件
void parseMemInfo(std::map<std::string, uint64_t>& memData) {
    std::ifstream meminfo("/proc/meminfo");
    if (!meminfo.is_open()) {
        std::cerr << "Failed to open /proc/meminfo" << std::endl;
        return;
    }

    std::string line;
    while (std::getline(meminfo, line)) {
        size_t colonPos = line.find(':');
        if (colonPos == std::string::npos) continue;

        std::string key = trim(line.substr(0, colonPos));
        std::string valuePart = trim(line.substr(colonPos + 1));
        
        uint64_t value = 0;
        if (stringToULongLong(split(valuePart, ' ')[0], value)) {
            memData[key] = value * 1024; // 单位是KB，转换为字节
        }
    }
    meminfo.close();
}


MemoryInfo getMemoryInfo() {
    std::map<std::string, uint64_t> memData;
    parseMemInfo(memData);

    MemoryInfo info;
    info.total = memData["MemTotal"];
    info.free = memData["MemFree"];
    // MemAvailable是更现代、更准确的可用内存指标
    info.available = memData["MemAvailable"] > 0 ? memData["MemAvailable"] : (memData["MemFree"] + memData["Buffers"] + memData["Cached"]);
    
    if (info.total > 0) {
        info.used = info.total - info.available;
        info.usagePercent = static_cast<double>(info.used) / info.total * 100.0;
    }
    
    return info;
}

SwapInfo getSwapInfo() {
    std::map<std::string, uint64_t> memData;
    parseMemInfo(memData);

    SwapInfo info;
    info.total = memData["SwapTotal"];
    info.free = memData["SwapFree"];
    
    if (info.total > 0) {
        info.used = info.total - info.free;
        info.usagePercent = static_cast<double>(info.used) / info.total * 100.0;
    }
    return info;
}

SystemMemoryInfo getSystemMemoryInfo() {
    std::map<std::string, uint64_t> memData;
    parseMemInfo(memData);
    
    SystemMemoryInfo info;
    // Memory
    info.memory.total = memData["MemTotal"];
    info.memory.free = memData["MemFree"];
    info.memory.available = memData["MemAvailable"] > 0 ? memData["MemAvailable"] : (memData["MemFree"] + memData["Buffers"] + memData["Cached"]);
    if (info.memory.total > 0) {
        info.memory.used = info.memory.total - info.memory.available;
        info.memory.usagePercent = static_cast<double>(info.memory.used) / info.memory.total * 100.0;
    }
    // Swap
    info.swap.total = memData["SwapTotal"];
    info.swap.free = memData["SwapFree"];
    if (info.swap.total > 0) {
        info.swap.used = info.swap.total - info.swap.free;
        info.swap.usagePercent = static_cast<double>(info.swap.used) / info.swap.total * 100.0;
    }

    return info;
}

std::string MemoryInfo::toString() const {
    std::stringstream ss;
    ss.precision(1);
    ss << "Memory: Total=" << utils::UnitConverter::formatBytes(total)
       << ", Used=" << utils::UnitConverter::formatBytes(used)
       << ", Available=" << utils::UnitConverter::formatBytes(available)
       << ", Usage=" << std::fixed << usagePercent << "%";
    return ss.str();
}

std::string SwapInfo::toString() const {
    std::stringstream ss;
    ss.precision(1);
    ss << "Swap: Total=" << utils::UnitConverter::formatBytes(total)
       << ", Used=" << utils::UnitConverter::formatBytes(used)
       << ", Free=" << utils::UnitConverter::formatBytes(free)
       << ", Usage=" << std::fixed << usagePercent << "%";
    return ss.str();
}

} // namespace memory
} // namespace sysmonitor
